#ifndef _SCENE_H_
#define _SCENE_H_

#include "Object.h"

#include <Renderer/Renderer.h>
#include <vector>
#include <Core/Uuid.h>

namespace Engine2D
{
    class Scene
    {
        REF_ENABLE
    public:
        Scene();
        virtual ~Scene() = default;

        std::shared_ptr<IObject> CreateBaseObject();
        std::shared_ptr<IObject> CreateCareraObject();
        void AddObject(std::shared_ptr<IObject> obj);
        bool RemoveObject(std::shared_ptr<IObject> obj);
        bool RemoveObject(Uuid uuid);
        size_t Size();
        std::shared_ptr<IObject> GetObjectByUuid(Uuid uuid);
        void Update();

        void Foreach(std::function<IObject::ForeachEnum(std::shared_ptr<IObject>)> fn, bool isRecurse = true) 
        {
            for (auto & item : m_objects) {
                if (fn(item) == IObject::ForeachEnum::Break) {
                    break;
                }
                item->Foreach(fn, isRecurse);
            }
        }

        template<typename... Components>
        void Foreach(std::function<IObject::ForeachEnum(std::shared_ptr<IObject>)> fn, bool isRecurse = true)
        {
            for (auto & item : m_objects) {
                if (IsAllTrue((!item->GetComponent<Components>().expired())...)) {
                    if (fn(item) == IObject::ForeachEnum::Break) {
                        break;
                    }
                }
                item->Foreach<Components...>(fn, isRecurse);
            }
        }

    private:
        std::vector<std::shared_ptr<IObject>> m_objects;
        size_t m_objectSize;
    };
    REF_REGISTER_CLASS(Scene,
        REF_REGISTER_FIELD(Scene, m_objectSize)
    )
} // namespace Engine2D


#endif